正则表达式
也叫正规表示法,常规表示法
用单个字符串来描述、匹配一系列符合某个语法规则的字符串
是对字符串操作的一种逻辑公式
用于处理文本和数据
一次拿出表达式和文本中的字符比较,如果每一个字符都能匹配,则匹配成功;否则匹配失败。
- 常用元字符
代码 | 说明 |
---|---|
. | 匹配除换行符以外的任意字符 |
[aeiou] | 匹配aeiou中的任意字符 |
\w | 匹配字母或数字或下划线 |
\s | 匹配任意的空白符 |
\d | 匹配数字 |
\b | 匹配单词的开始或结束 |
^ | 匹配字符串的开始 |
$ | 匹配字符串的结束 |
\A | 开头匹配 |
\Z | 结尾匹配 |
- 常用限定符
代码 | 说明 |
---|---|
* | 重复零次或更多次 |
+ | 重复一次或更多次 |
? | 重复零次或一次 |
{n} | 重复n次 |
{n,} | 重复n次或更多次 |
{n,m} | 重复n到m次 |
*? | 匹配模式变为非贪婪(尽可能少匹配字符)能不匹配就不匹配 |
+? | 匹配模式变为非贪婪(尽可能少匹配字符)只匹配一个 |
?? | 匹配模式变为非贪婪(尽可能少匹配字符) |
- 常用反义符
代码 | 说明 |
---|---|
\W | 匹配任意不是字母,数字,下划线,汉字的字符 |
\S | 匹配任意不是空白符的字符 |
\D | 匹配任意非数字的字符 |
\B | 匹配不是单词开头或结束的位置 |
[^x] | 匹配除了x以外的任意字符 |
[^aeiou] | 匹配除了aeiou这几个字母以外的任意字符 |
- 分组匹配
代码 | 说明 |
---|---|
竖线 | 匹配左右任意一个表达式 |
(ab) | 括号中表达式作为一个分组 |
\\ |
引用编号为num的分组匹配到的字符串 |
(?P |
分组起一个别名 |
(?P=name) | 引用别名为name的分组匹配字符串 |
典型实例
由26字母组成的字符串
^[A-Za-z]+$由26个字符和数字组成的字符串
^\w+$整数形式的字符串
^(+|-)?\d*$正整数形式的字符串
^+?[0-9]*[1-9][0-9]*$小数形式的字符串
^(+|-)?\d*\.[0-9]+$匹配中文字符
[\u4e00-\u9fa5]匹配国内手机号
(\+86-)?(131|132|133|155|182|183)-?\d{4}-?\d{4}匹配邮箱
\w{1,255}@\w+\.(com|org|edu|cn|gov)ip地址的点分十进制
(([1-9]?\d|1\d{2}|2[0-4]\d|25[0-5])\.){3}([1-9]?\d|1\d{2}|2[0-4]\d|25[0-5])
re库中主要的类
Pattern类
编译后的正则表达式对象
如:re.compile(r’(\d{5})-fa?’, re.UNICODE)
属性 | 描述 | 值 |
---|---|---|
flags | 当前模式的控制标记值 | 32 |
groupindex | 当前模式的分组索引,组名到组号的映射,字典形式 | {} |
groups | 当前模式的分组数量 | 1 |
pattern | 当前模式的正则表达式 | ‘(\d{5})-fa?’ |
方法 | 描述 |
---|---|
findall(string, pos=0, endpos=9223372036854775807) | 功能及用法同re中定义的函数 |
finditer(string, pos=0, endpos=9223372036854775807) | 功能及用法同re中定义的函数 |
fullmatch(string, pos=0, endpos=9223372036854775807) | 功能及用法同re中定义的函数 |
match(string, pos=0, endpos=9223372036854775807) | 功能及用法同re中定义的函数 |
scanner(string, pos=0, endpos=9223372036854775807) | |
search(string, pos=0, endpos=9223372036854775807) | 功能及用法同re中定义的函数 |
split(string, maxsplit=0) | 功能及用法同re中定义的函数 |
sub(repl, string, count=0) | 功能及用法同re中定义的函数 |
subn(repl, string, count=0) | 功能及用法同re中定义的函数 |
Match类
一次匹配的结果,包括匹配的各种信息
属性 | 描述 |
---|---|
lastgroup | |
lastindex | |
pos | 正则表达式搜索文本的开始位置 |
endpos | 正则表达式搜索文本的结束位置 |
re | 本次匹配使用的pattern对象 |
regs | |
string | 待匹配的文本 |
方法 | 描述 |
---|---|
start(self, group=0, /) | 匹配到的字符串在原始字符串的开始位置 |
end(self, group=0, /) | 匹配到的字符串在原始字符串的结束位置 |
expand(self, /, template) | |
group(…) | 获得匹配到的字符串,参数可以是分组编号 |
groupdict(self, /, default=None) | |
groups(self, /, default=None) | |
span(self, group=0, /) | 返回二元组(m.start(group), m.end(group)) |
- flags控制标记
代码 | 数值 | 说明 |
---|---|---|
re.TEMPLATE(T) | 1 | 模板 |
re.IGNORECASE(I) | 2 | 匹配时忽略大小写 |
re.LOCALE(L) | 4 | 匹配\w,\W,\b,\B,\s,\S是依赖locale 字符集 |
re.MULTLINE(M) | 8 | 匹配多行,影响^和$;设置后会匹配每一行的开头和结尾 |
re.DOTALL(S) | 16 | 影响. 的匹配行为。默认.不匹配换行,设置后会匹配换行 |
re.UNICODE(U) | 32 | 匹配\w,\W,\b,\B,\s,\S是依赖Unicode 字符集 |
re.VERBOSE(X) | 64 | 忽略匹配模式字符串中的空格,方括号内和被转义的空格除外 |
re库中主要的函数(12个)
search(pattern, string, flags=0)
扫描字符串,全文搜索匹配模式的子串,匹配到的第一个内容返回match对象,没匹配到返回None
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16import re
match = re.search(r'\d{6}', 'BIT100081 TSU100084')
if match:
print(type(match))
print(match.re)
print(match.pos, match.endpos)
print(match.group())
print(match.span())
'''
<class 're.Match'>
re.compile('\\d{6}')
0 19
100081
(3, 9)
'''match(pattern, string, flags=0)
从字符串的第1个字符开始匹配,匹配到内容返回match对象,没匹配到返回None
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26import re
#-----------------------------------------------
match = re.match(r'[1-9]\d{5}', 'BIT100081 TSU100084')
if match:
print(match.group())
# 没有匹配到
#-----------------------------------------------
match = re.match(r'[1-9]\d{5}', '100081BIT 100084TSU')
if match:
print(match.group())
# 100081
#-----------------------------------------------
m = re.match(r'^(\d{3})-(\d{3,8})$', '010-12345')
print(m.group(0))
print(m.group(1))
print(m.group(2))
# 010-12345
# 010
# 12345
#-----------------------------------------------
t = '19:05:30'
m = re.match(r'^(0[0-9]|1[0-9]|2[0-3]|[0-9])\:(0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]|[0-9])\:(0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]|[0-9])$', t)
print(m.groups())
# ('19', '05', '30')finditer(pattern, string, flags=0)
搜索字符串,返回一个匹配结果的迭代类型,每个迭代元素是Match对象或None
1
2
3
4
5
6
7import re
for m in re.finditer(r'[1-9]\d{5}', 'BIT100081 TSU100084'):
if m:
print(m.group())
#100081
#100084findall(pattern, string, flags=0)
搜索字符串,以列表类型返回全部能匹配的子串
1
2
3
4
5import re
ls = re.findall(r'[1-9]\d{5}', 'BIT100081 TSU100084')
print(ls)
# ['100081', '100084']split(pattern, string, maxsplit=0, flags=0)
将一个字符串按照正则表达式匹配结果进行分割,返回列表类型
1
2
3
4
5
6
7import re
ls = re.split(r'[1-9]\d{5}', 'BIT100081 TSU100084')
print(ls)
# ['BIT', ' TSU', '']
ls = re.split(r'[1-9]\d{5}', 'BIT100081 TSU100084', maxsplit=1)
print(ls)
# ['BIT', ' TSU100084']sub(pattern, repl, string, count=0, flags=0)
在一个字符串中替换所有匹配正则表达式的子串,返回替换后的字符串
repl是用来替换的字符串
string是待匹配字符串
count是匹配的最大替换次数
1
2
3
4import re
after = re.sub(r'[1-9]\d{5}', ':zipcode', 'BIT100081 TSU100084')
print(after)
#'BIT:zipcode TSU:zipcode'subn(pattern, repl, string, count=0, flags=0)
参数含义和函数功能与re.sub相同,返回一个二元组(替换后的字符串,实际替换的次数)
1
2
3import re
re.subn(r'[1-9]\d{5}', ':zipcode', 'BIT100081 TSU100084')
#('BIT:zipcode TSU:zipcode', 2)compile(pattern, flags=0)
编译一个正则表达式模式,返回Pattern对象,可以一次编译,多次使用。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28import re
reg = re.compile(r'(([1-9]?\d|1\d{2}|2[0-4]\d|25[0-5])\.){3}([1-9]?\d|1\d{2}|2[0-4]\d|25[0-5])')
print(type(reg))
# <class 're.Pattern'>
print(reg.flags)
# 32
print(reg.pattern)
# (([1-9]?\d|1\d{2}|2[0-4]\d|25[0-5])\.){3}([1-9]?\d|1\d{2}|2[0-4]\d|25[0-5])
print(reg.groups)
# 3
print(reg.groupindex)
# {}
match = reg.search('某个IP地址是192.168.1.1。')
if match:
print(match.group())
print(match.span())
print(match.groups())
'''
192.168.1.1
(7, 18)
('1.', '1', '1')
'''template(pattern, flags=0)
编译一个模板模式,返回Pattern对象。
escape(pattern)
对字符串进行正则转义,除了字母和数字fullmatch(pattern, string, flags=0)
purge()